package sprites;

import java.awt.Graphics;
import java.awt.Point;
import java.awt.Polygon;
import java.awt.Rectangle;
import java.util.Set;

import util.DrawSet;
import classes.Direction;

public class RoundedCornersSprite extends PointSetSprite {

	public RoundedCornersSprite(Point pos, Set<Point> selected) {
		super(pos, selected);
	}
	
	@Override
	public void drawStuff(Graphics G, Point P, Rectangle R) {
		FillEverything(G, P, R);
		DrawEverything(G, P, R);
	}
	
	private void DrawEverything(Graphics G, Point P, Rectangle R) {
		DrawOddSoftCorners(G, P, R);
		DrawHardCorners(G, P, R);
		DrawInternalSoftCorners(G, P, R);
		DrawExternalSoftCorners(G, P, R);		
	}
	private void DrawOddSoftCorners(Graphics G, Point P, Rectangle R) {
		Rectangle Rn = new Rectangle(R.x, R.y-R.height, 	R.width,R.height);
		Rectangle Re = new Rectangle(R.x+R.width, R.y, 		R.width,R.height);
		Rectangle Rw = new Rectangle(R.x-R.width, R.y, 		R.width,R.height);
		Rectangle Rs = new Rectangle(R.x, R.y+R.height, 	R.width,R.height);
		
		if (containsPoint(P)) {
			if	(	containsPoint(DrawSet.getNW(P))
				&&	!containsPoint(DrawSet.getN(P))
				&&	!containsPoint(DrawSet.getW(P))
				)
			{
				drawLine(G,
					DrawSet.getPoint(Direction.south, Rn),
					DrawSet.getPoint(Direction.west, Rn)
				);
				drawLine(G,
					DrawSet.getPoint(Direction.north, Rw),
					DrawSet.getPoint(Direction.east, Rw)
				);
			}
			if	(	containsPoint(DrawSet.getNE(P))
					&&	!containsPoint(DrawSet.getN(P))
					&&	!containsPoint(DrawSet.getE(P))
					)
			{
				drawLine(G,
					DrawSet.getPoint(Direction.south, Rn),
					DrawSet.getPoint(Direction.east, Rn)
				);
				drawLine(G,
					DrawSet.getPoint(Direction.north, Re),
					DrawSet.getPoint(Direction.west, Re)
				);
			}
			if	(	containsPoint(DrawSet.getSE(P))
					&&	!containsPoint(DrawSet.getS(P))
					&&	!containsPoint(DrawSet.getE(P))
					)
			{
				drawLine(G,
					DrawSet.getPoint(Direction.north, Rs),
					DrawSet.getPoint(Direction.east, Rs)
				);
				drawLine(G,
					DrawSet.getPoint(Direction.south, Re),
					DrawSet.getPoint(Direction.west, Re)
				);
			}
			if	(	containsPoint(DrawSet.getSW(P))
					&&	!containsPoint(DrawSet.getS(P))
					&&	!containsPoint(DrawSet.getW(P))
					)
			{
				drawLine(G,
					DrawSet.getPoint(Direction.north, Rs),
					DrawSet.getPoint(Direction.west, Rs)
				);
				drawLine(G,
					DrawSet.getPoint(Direction.south, Rw),
					DrawSet.getPoint(Direction.east, Rw)
				);
			}
		}
	}
	private void DrawHardCorners(Graphics G, Point P, Rectangle R) {
		if (containsPoint(P)) {
			if	(	!containsPoint(DrawSet.getNW(P))
				&&	!containsPoint(DrawSet.getN(P))
				&&	containsPoint(DrawSet.getW(P))
				)
			{
				drawLine(G,
					DrawSet.getPoint(Direction.north_west, R),
					DrawSet.getPoint(Direction.north, R)
				);
			}
			
			if	(	!containsPoint(DrawSet.getNE(P))
				&&	!containsPoint(DrawSet.getN(P))
				&&	containsPoint(DrawSet.getE(P))
				)
			{
				drawLine(G,
					DrawSet.getPoint(Direction.north_east, R),
					DrawSet.getPoint(Direction.north, R)
				);
			}
			
			if	(	!containsPoint(DrawSet.getNE(P))
				&&	!containsPoint(DrawSet.getE(P))
				&&	containsPoint(DrawSet.getN(P))
				)
			{
				drawLine(G,
					DrawSet.getPoint(Direction.north_east, R),
					DrawSet.getPoint(Direction.east, R)
				);
			}
			
			if	(	!containsPoint(DrawSet.getSE(P))
				&&	!containsPoint(DrawSet.getE(P))
				&&	containsPoint(DrawSet.getS(P))
				)
			{
				drawLine(G,
					DrawSet.getPoint(Direction.south_east, R),
					DrawSet.getPoint(Direction.east, R)
				);
			}
			
			if	(	!containsPoint(DrawSet.getSE(P))
				&&	!containsPoint(DrawSet.getS(P))
				&&	containsPoint(DrawSet.getE(P))
				)
			{
				drawLine(G,
					DrawSet.getPoint(Direction.south_east, R),
					DrawSet.getPoint(Direction.south, R)
				);
			}
			
			if	(	!containsPoint(DrawSet.getSW(P))
					&&	!containsPoint(DrawSet.getW(P))
					&&	containsPoint(DrawSet.getS(P))
					)
				{
					drawLine(G,
						DrawSet.getPoint(Direction.south_west, R),
						DrawSet.getPoint(Direction.west, R)
					);
				}
			
			
			if	(	!containsPoint(DrawSet.getSW(P))
				&&	!containsPoint(DrawSet.getS(P))
				&&	containsPoint(DrawSet.getW(P))
				)
			{
				drawLine(G,
					DrawSet.getPoint(Direction.south_west, R),
					DrawSet.getPoint(Direction.south, R)
				);
			}
			
			if	(	!containsPoint(DrawSet.getNW(P))
				&&	!containsPoint(DrawSet.getW(P))
				&&	containsPoint(DrawSet.getN(P))
				)
			{
				drawLine(G,
					DrawSet.getPoint(Direction.north_west, R),
					DrawSet.getPoint(Direction.west, R)
				);
			}
		}
	}
	private void DrawInternalSoftCorners(Graphics G, Point P, Rectangle R) {
		Rectangle Rnw = new Rectangle(R.x-R.width, R.y-R.height, 	R.width,R.height);
		Rectangle Rne = new Rectangle(R.x+R.width, R.y-R.height, 	R.width,R.height);
		Rectangle Rsw = new Rectangle(R.x-R.width, R.y+R.height, 	R.width,R.height);
		Rectangle Rse = new Rectangle(R.x+R.width, R.y+R.height, 	R.width,R.height);
		
		if (containsPoint(P)) {
			if (	containsPoint(DrawSet.getW(P))
				&&	containsPoint(DrawSet.getN(P))
				&&	!containsPoint(DrawSet.getNW(P))
				)
			{
				drawLine(G, 
					DrawSet.getPoint(Direction.east, Rnw),
					DrawSet.getPoint(Direction.south, Rnw)
				);
			}
			
			if (	containsPoint(DrawSet.getE(P))
				&&	containsPoint(DrawSet.getN(P))
				&&	!containsPoint(DrawSet.getNE(P))
				)
				{
					drawLine(G, 
						DrawSet.getPoint(Direction.west, Rne),
						DrawSet.getPoint(Direction.south, Rne)
					);
				}
			
			if (	containsPoint(DrawSet.getW(P))
				&&	containsPoint(DrawSet.getS(P))
				&&	!containsPoint(DrawSet.getSW(P))
				)
				{
					drawLine(G, 
						DrawSet.getPoint(Direction.east, Rsw),
						DrawSet.getPoint(Direction.north, Rsw)
					);
				}
			
			if (	containsPoint(DrawSet.getE(P))
					&&	containsPoint(DrawSet.getS(P))
					&&	!containsPoint(DrawSet.getSE(P))
					)
				{
					drawLine(G, 
						DrawSet.getPoint(Direction.west, Rse),
						DrawSet.getPoint(Direction.north, Rse)
					);
				}
			
		}
	}
	private void DrawExternalSoftCorners(Graphics G, Point P, Rectangle R) {
		if (containsPoint(P)) {
			if (	!containsPoint(DrawSet.getW(P))
				&&	!containsPoint(DrawSet.getN(P))
				&&	!containsPoint(DrawSet.getNW(P))
				)
			{
				drawLine(G, 
					DrawSet.getPoint(Direction.west, R),
					DrawSet.getPoint(Direction.north, R)
				);
			}
			if (	!containsPoint(DrawSet.getW(P))
				&&	!containsPoint(DrawSet.getS(P))
				&&	!containsPoint(DrawSet.getSW(P))
				)
			{
				drawLine(G, 
					DrawSet.getPoint(Direction.west, R),
					DrawSet.getPoint(Direction.south, R)
				);
			}
			if (	!containsPoint(DrawSet.getE(P))
				&&	!containsPoint(DrawSet.getS(P))
				&&	!containsPoint(DrawSet.getSE(P))
				)
			{
				drawLine(G, 
					DrawSet.getPoint(Direction.east, R),
					DrawSet.getPoint(Direction.south, R)
				);
			}
			if (	!containsPoint(DrawSet.getE(P))
				&&	!containsPoint(DrawSet.getN(P))
				&&	!containsPoint(DrawSet.getNE(P))
				)
			{
				drawLine(G, 
					DrawSet.getPoint(Direction.east, R),
					DrawSet.getPoint(Direction.north, R)
				);
			}
		}
	}
	
	private void FillEverything(Graphics G, Point P, Rectangle R) {
		Rectangle Rn = new Rectangle(R.x, 			R.y-R.height, 	R.width,R.height);
		Rectangle Re = new Rectangle(R.x+R.width,	R.y, 			R.width,R.height);
		Rectangle Rs = new Rectangle(R.x, 			R.y+R.height, 	R.width,R.height);
		Rectangle Rw = new Rectangle(R.x-R.width,	R.y, 			R.width,R.height);

		Polygon	center = makePolygon(new Point[] {
			DrawSet.getPoint(Direction.north,	R),
			DrawSet.getPoint(Direction.east,	R),
			DrawSet.getPoint(Direction.south,	R),
			DrawSet.getPoint(Direction.west,	R)
		});
		Polygon	nw = makePolygon(new Point[] {
			DrawSet.getPoint(Direction.north_west,	R),
			DrawSet.getPoint(Direction.north,		R),
			DrawSet.getPoint(Direction.west,		R)
		});
		Polygon	ne = makePolygon(new Point[] {
			DrawSet.getPoint(Direction.north_east,	R),
			DrawSet.getPoint(Direction.east,		R),
			DrawSet.getPoint(Direction.north,		R)
		});
		Polygon	se = makePolygon(new Point[] {
			DrawSet.getPoint(Direction.south_east,	R),
			DrawSet.getPoint(Direction.south,		R),
			DrawSet.getPoint(Direction.east,		R)
		});
		Polygon	sw = makePolygon(new Point[] {
			DrawSet.getPoint(Direction.south_west,	R),
			DrawSet.getPoint(Direction.west,		R),
			DrawSet.getPoint(Direction.south,		R)
		});
		
		boolean	fillNW = 
			(	(	containsPoint(P) 
				&&	(	containsPoint(DrawSet.getN(P))
					||	containsPoint(DrawSet.getNW(P))
					||	containsPoint(DrawSet.getW(P))
					)
				)
			||	(	!containsPoint(P) 
				&&	(	containsPoint(DrawSet.getN(P))
					&&	containsPoint(DrawSet.getW(P))
					)
				)
			);
		boolean fillNE = 
			(	(	containsPoint(P) 
				&&	(	containsPoint(DrawSet.getN(P))
					||	containsPoint(DrawSet.getNE(P))
					||	containsPoint(DrawSet.getE(P))
					)
				)
			||	(	!containsPoint(P) 
				&&	(	containsPoint(DrawSet.getE(P))
					&&	containsPoint(DrawSet.getN(P))
					)
				)
			);
		boolean	fillSE =
			(	(	containsPoint(P) 
				&&	(	containsPoint(DrawSet.getS(P))
					||	containsPoint(DrawSet.getSE(P))
					||	containsPoint(DrawSet.getE(P))
					)
				)
			||	(	!containsPoint(P) 
				&&	(	containsPoint(DrawSet.getE(P))
					&&	containsPoint(DrawSet.getS(P))
					)
				)
			);
		boolean	fillSW = 
			(	(	containsPoint(P) 
				&&	(	containsPoint(DrawSet.getS(P))
					||	containsPoint(DrawSet.getSW(P))
					||	containsPoint(DrawSet.getW(P))
					)
				)
			||	(	!containsPoint(P) 
				&&	(	containsPoint(DrawSet.getW(P))
					&&	containsPoint(DrawSet.getS(P))
					)
				)
			);

		boolean fillCenter	= containsPoint(P);
		
			//
			// Do the filling
			//
			
			if (fillNW) 	{	G.fillPolygon(nw);		}
			if (fillNE) 	{	G.fillPolygon(ne);		}
			if (fillSE) 	{	G.fillPolygon(se);		}
			if (fillSW) 	{	G.fillPolygon(sw);		}
			if (fillCenter) {	G.fillPolygon(center);	}
		
		if (containsPoint(P)) {
			if (!containsPoint(DrawSet.getN(P)))	{	FillEverything(G, DrawSet.getN(P), Rn);	}
			if (!containsPoint(DrawSet.getE(P)))	{	FillEverything(G, DrawSet.getE(P), Re);	}
			if (!containsPoint(DrawSet.getS(P)))	{	FillEverything(G, DrawSet.getS(P), Rs);	}
			if (!containsPoint(DrawSet.getW(P)))	{	FillEverything(G, DrawSet.getW(P), Rw);	}
		}
	}
	
	private static final Polygon makePolygon(Point P[]) {
		Polygon poly = new Polygon();
		int		i;
		for(i=0; i<P.length; i++) {
			poly.addPoint(P[i].x, P[i].y);
		}
		return poly;
	}
	
}
